package compilers.AST.expression;

import java.io.PrintStream;

import compilers.AST.Node;
import compilers.AST.types.MyType;
import compilers.AST.types.TypeSpecifier;
import compilers.compiler.PGenerator;
import compilers.exceptions.SemanticalException;
import compilers.symbolTable.SymbolTable;
import compilers.symbolTable.SymbolTableScope;

public class Expression extends Term {
	
	private Logical fLogical;
	private TypeSpecifier fConvertTo = null;

	public Expression() {
		
	}
	
	public Expression(int lineNr) {
		super(lineNr);
	}
	
	public void print(int identLevel) {
		println(identLevel, "Expression");
		fLogical.print(identLevel+1);
	}
	
	public void checkSemantics(SymbolTableScope currentScope) throws SemanticalException {
		fLogical.checkSemantics(currentScope);
	}
	
	public void setLogical(Logical logical) {
		fLogical = logical;
	}
	
	public int getResultType(SymbolTableScope currentScope) {
		if(this.fConvertTo == null) {
			return fLogical.getResultType(currentScope);
		} else {
			return this.fConvertTo.getType(currentScope);
		}
	}
	
	public int getOriginalType(SymbolTableScope currentScope) {
		return fLogical.getOriginalType(currentScope);
	}
	
	public boolean isConstant(SymbolTableScope currentScope) {
		return fLogical.isConstant(currentScope);
	}
	
	public boolean isArray(SymbolTableScope currentScope) {
		return fLogical.isArray(currentScope);
	}
	
	public String getArrayIdent(SymbolTableScope currentScope) {
		return fLogical.getArrayIdent(currentScope);
	}
	
	public MyType calculateValue(SymbolTableScope currentScope) {
		return fLogical.calculateValue(currentScope);
	}
	
	public void generatePcode(PGenerator pGen, SymbolTableScope currentScope) {
		if (fLogical.isConstant(currentScope)) {
			TypeSpecifier firstResultType = new TypeSpecifier(fLogical.getResultType(currentScope));
			pGen.load(firstResultType.getPType(currentScope), fLogical.calculateValue(currentScope).valueToString());
		} else {
			fLogical.generatePcode(pGen, currentScope);
		}
		
		//Convert if necessary
		if(this.fConvertTo != null) {
			pGen.conv(TypeSpecifier.getPType(this.getOriginalType(currentScope)), this.fConvertTo.getPType(currentScope));
		}
	}
	
	public void setConvertTo(TypeSpecifier type) {
		this.fConvertTo = type;
	}	
}
